﻿package src.computation {
	
	/**
	* 
	* Reliability project
	* -----------------------
	* @author  Dmitrij Boycov
	* @mail    dmitry.boycov@gmail.com
	* @date    April 27, 2010
	* @version 1
	* 
	*/
	
	import src.entity.Element;
	import src.computation.distributionLaw.AbstractLaw;
	import src.computation.TimeLine;
	import src.computation.Recovery;
	
	public class CElement extends CEntity implements ICEntity,  ICObjectOfScheme {		
		
		public var distributionLaw;
		public var _recovery:Recovery;
		public var stockId = -1;
		public var inLink = null		// id link
		public var outLink = null		// id link
		public const type = Element.TYPE
		private var probability;
		private var time:Number = 0;
		private var timeOfWork = null;
		
		/**
		 * timeOfRecovery
		 * -1 mins this elements is not recovered. And time of recovery equal infinite.
		 */
		private var timeOfRecovery = null;
		
		/**
		 * timeLine
		 * this property are need for simulation method that considere recovery
		 */
		private var timeLine:TimeLine = null;
		
		public function CElement(){	
		}		
		
		/**
		 * setParamsByStock
		 * If element have type, than his params can be init by type params
		 * @param	obj
		 */
		public function setParamsByStock(obj) {
			if (obj.law) {
				this.distributionLaw = obj.law;
			}
			if (obj.recovery) {
				this._recovery = obj.recovery
			}
		}
		
		public function addLink(link:CLink,allLink):Boolean {
			if (inLink == null) {
				inLink = link.id;
				return true;
			}
			if (outLink == null) {
				outLink = link.id;
				return true;
			}
			return false;
		}
		
		public function unLink(id:Number):void {
			if (inLink == id) {
				inLink = null;
			}
			if (outLink == id) {
				outLink = null;
			}			
		}
		
		public function setTimeLine(tm) {
			this.timeLine = tm;
		}
		
		public function getTimeLine() {
			return this.timeLine;
		}
		
		public function getTime() {
			return this.time;
		}
		
		public function setTime(t:Number) {
			this.time = t;
		}
		
		public function setProbability(p) {
			this.probability = p;
		}
		
		public function getProbability() {			
			if (!this.probability) {
				if (this.distributionLaw == null) {
					this.distributionLaw = new AbstractLaw();
				}
				this.probability = this.distributionLaw.getProbabilty(this.time);
			}
			return this.probability;
		}
		
		public function setTimeOfWork(t) {
			this.timeOfWork = t;
		}
		
		/**
		 *  getTimeOfOperation
		 *  This fuction are need for simulation with recovery.
		 *  Time of operation is work time and recovery time.
		 */
		public function getTimeOfOperation () {
			return this.timeLine.getCurrentTime();
		}
		
		private function generateTimeOfRecovery() {
			if (this._recovery == null) {
				// This elements is not recovered.
				// Time of recovery equal infinite.
				return -1;
			}
			this._recovery.setSystemWorkTime(this.time);
			return this._recovery.getTime();	
		}
		
		public function getTimeOfRecovery() {			
			if (this.timeOfRecovery == null) {
				this.timeOfRecovery = this.generateTimeOfRecovery();				
			}			
			return this.timeOfRecovery;
		}
		
		public function setTimeOfRecovery(tr) {
			this.timeOfRecovery = tr;
		}
		
		private function generateTimeOfWork() {
			if (this.distributionLaw == null) {					
				this.distributionLaw = new AbstractLaw();
			}				
			this.distributionLaw.setTime(this.time);
			return this.distributionLaw.random();
		}
		
		public function getTimeOfWork() {			
			if (this.timeOfWork == null) {
				this.timeOfWork = this.generateTimeOfWork();
			}			
			return this.timeOfWork;
		}
		
		public function print():void {			
			trace("--"+this.type + "------------------");
			this.printBase();
			trace("id inlink:" + this.inLink);
			trace("id outlink:" + this.outLink);
			if (this.distributionLaw != null) {
				trace("low:" + this.distributionLaw.desc);
			}else {
				trace("low:" + "empty");
			}			
			trace("probability:" + this.probability);
			trace("time of work:" + this.timeOfWork);
			if (this.timeLine != null) {
				trace("Times:");
				this.timeLine.print();
			}
			trace("----------------------------");
		}
		
		/**
		 * work
		 * generate time of work.
		 * return true if set time of work 
		 * return false if preset time interval is filled; or other failed situation
		 * @return - boolean
		 */
		public function work():Boolean {
			if(this.timeLine!=null){
				var t = this.generateTimeOfWork();
				return this.timeLine.addWorKTime(t);
			}
			return false;
		}
		
		public function nowWork():Boolean {
			return this.timeLine.nowWork();
		}
		
		/**
		 * getFirstWorkTime
		 * This function is used in simulation with recovery
		 * @return number
		 */
		public function getFirstWorkTime():Number {
			if (this.timeLine != null) {
				return this.timeLine.getFirstWorkTime();
			}
			return 0;
		}
		
		
		/**
		 * recovery
		 * generate time of recovery.
		 * return true if set time of recovery 
		 * return false if preset time interval is filled; or other failed situation
		 * @return - boolean
		 */
		public function recovery():Boolean {
			if(this.timeLine!=null){
				var t = this.generateTimeOfRecovery();				
				return this.timeLine.addRecoveryTime(t);
			}
			return false;
		}
		
		/**
		 * replacement
		 * generate time of replacement.
		 * return true if set time of replacement 
		 * return false if preset time interval is filled; or other failed situation
		 * @return - boolean
		 */
		public function replacement():Boolean {			
			if(this.timeLine!=null){
				var t = this.getTimeOfReplacement();
				return this.timeLine.addRecoveryTime(t);
			}
			return false;
		}
		
		public function getTimeOfReplacement() {
			return 8;
		}
		
		public function unitRecoveryTime(tl:TimeLine) {
			if (this.timeLine != null && tl != null) {
				this.timeLine.unitRecoveryTime(tl);	
			}
		}
		
		public function getKG() {
			if (this.timeLine != null) {
				return this.timeLine.getKG();
			}
			return 0;
		}
		
		public function unitWorkTime(tl:TimeLine) {
			if (this.timeLine != null && tl != null) {
				this.timeLine.unitWorkTime(tl);	
			}
		}
		
		/**
		 * clone
		 * return copy of this object
		 */
		public override function clone() {			
			var cloneObj:CElement = new CElement();
			// common parametrs
			cloneObj.id = this.id;
			cloneObj.name = this.name;
			cloneObj.description = this.description;
			// specific parametrs
			cloneObj.distributionLaw = this.distributionLaw;
			cloneObj._recovery = this._recovery;
			cloneObj.stockId = this.stockId;
			cloneObj.inLink = this.inLink;		// id link
			cloneObj.outLink = this.outLink;	// id link			
			cloneObj.setProbability(this.getProbability());
			cloneObj.setTime(this.getTime());
			cloneObj.setTimeOfWork(this.timeOfWork);
			cloneObj.setTimeLine(this.timeLine);
			cloneObj.setTimeOfRecovery(this.timeOfRecovery);
			return cloneObj;
		}
	}
	
}